<?php

/**
 * Capital Direct Lending (http://www.philbsd.com/cdl)
 *
 * Copyright (C) 2008 Philippine Business Solution Developers <http://www.philbsd.com>
 * All rights reserved.
 *
 *
 * LICENSE
 *
 * This source file is subject to the GNU General Public License v3 license
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.gnu.org/licenses/gpl-3.0.txt
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@philbsd.com so we can send you a copy immediately.
 *
 * @copyright  (c) 2008 Philippine Business Solution Developers. (http://www.philbsd.com)
 * @license    http://www.gnu.org/licenses/gpl-3.0.txt
 * @version    $Id: ModuleController.php 38 2008-03-09 08:26:00Z philbsd $
 */

class ModuleController extends Philbsd_Controller_Action
{
    protected $_session;

	protected $_dirModule;

	protected $_tableInstance;

	protected $_moduleResourceTable;

	protected $_moduleResourcePrivilegeTable;

    public function init()
    {
        $this->_session = new Zend_Session_Namespace(__CLASS__);
		$this->_tableInstance = new Philbsd_Model_Modules();
		$this->_moduleResourceTable = new Philbsd_Model_Module_Resources();
		$this->_moduleResourcePrivilegeTable = new Philbsd_Model_Module_Resource_Privileges();
		$this->_dirModule = dirname(dirname(dirname(__FILE__)));
    }

    public function indexAction()
    {
		if (isset($_POST['btnSubmit'])) {
			$moduleRowSet = $this->_tableInstance->fetchAll();
			while ($moduleRow = $moduleRowSet->current()) {
				// check the status of the active in the current id
				if ((bool)$moduleRow->active !== isset($_POST['active_'.$moduleRow->id])) {
					$moduleRow->active = isset($_POST['active_'.$moduleRow->id])? 1 : 0;
					$moduleRow->save();
					$this->_session->message .= "Module named {$moduleRow->name} modified successfully.<br \>\n";
				}
				$moduleRowSet->next();
			}

			$this->_redirect('admin/module');
		}

		// traverse all folders inside the modules directory
		$moduleInfo = array();
		if ($handle = opendir($this->_dirModule)) {
			while (false !== ($file = readdir($handle))) {
				if ($file != '.' && $file != '..' && $file{0} != '.') {
					$filename = $this->_dirModule . DS . $file . DS . 'module_info.xml';
					if (!file_exists($filename)) {
						continue;
					}
					$xmlConfig = new Zend_Config_Xml($filename, 'module');
					$moduleInfo[$file] = $xmlConfig->toArray();
				}
			}
			closedir($handle);
		}

		// get all module names in the database
		$installedModuleNames = array();
		$modules = array();
		$moduleRowSet = $this->_tableInstance->fetchAll();
		while ($moduleRow = $moduleRowSet->current()) {
			$module = $moduleRow->toArray();
			if (array_key_exists($moduleRow->name, $moduleInfo)) {
				unset($moduleInfo[$moduleRow->name]);
			}
			$modules['installed'][] = $module;
			$moduleRowSet->next();
		}
		$modules['uninstalled'] = $moduleInfo;

		$this->view->records = $modules;

		if (isset($this->_session->message)) {
			$this->view->message = $this->_session->message;
			unset($this->_session->message);
		}

		$this->render();
    }

	function viewAction()
	{
		$params = $this->getRequest()->getUserParams();
		if (!isset($params['id'])) {
			$this->_redirect('admin/module');
		}
		$moduleRowSet = $this->_tableInstance->find($params['id']);
		if (!$moduleRow = $moduleRowSet->current()) {
			$this->_redirect('admin/module');
		}
		// get all records in the module_resources table which module id is equal to the parameter's id
		$records = $moduleRow->toArray();
		$moduleResourceRowSet = $this->_moduleResourceTable->fetchAll("module_id = {$moduleRow->id}");

		// traverse all the data in module_resources table whose module_id equals to the parameter's id
		while ($moduleResourceRow = $moduleResourceRowSet->current()) {
			$resourceRow = $moduleResourceRow->findParentRow('Philbsd_Model_Resources');
			$records['resources'][$moduleResourceRow->resource_id] = $resourceRow->toArray();
			$moduleResourcePrivilegeRowSet =
					$this->_moduleResourcePrivilegeTable->fetchAll("module_resource_id = {$moduleResourceRow->id}");
			while ($moduleResourcePrivilegeRow = $moduleResourcePrivilegeRowSet->current()) {
				$privilegeRow = $moduleResourcePrivilegeRow->findParentRow('Philbsd_Model_Privileges');
				$records['resources'][$moduleResourceRow->resource_id]['privileges'][] = $privilegeRow->toArray();
				$moduleResourcePrivilegeRowSet->next();
			}
			$moduleResourceRowSet->next();
		}

		$this->view->records = $records;
		$this->render();
	}

	public function installAction()
	{
		if (isset($_POST['btnCancel'])) {
			$this->_redirect('admin/module');
		}

		$params = $this->getRequest()->getUserParams();
		// check if name exists in request
		if (!isset($params['name'])) {
			$this->_redirect('admin/module');
		}

		// check if name exists in database, if exists it will redirect back to the module list
		$moduleRowSet = $this->_tableInstance->fetchAll("name = '{$params['name']}'");
		if ($moduleRow = $moduleRowSet->current()) {
			$this->_redirect('admin/module');
		}

		// check if name is not a directory, if so then it will redirect back to the module list
		$moduleName = $this->_dirModule . DS . $params['name'];
		if (!is_dir($moduleName)) {
			$this->_redirect('admin/module');
		}

		$filename = $moduleName . DS . 'module_info.xml';
		if (!file_exists($filename)) {
			$this->_session->message = "module_info.xml not found in the {$params['name']} module directory.";
			$this->_redirect('admin/module');
		}
		$xmlConfig = new Zend_Config_Xml($filename, 'module');

		$record['name'] = $params['name'];
		$this->view->record = $record;
		if (isset($_POST['btnSubmit'])) {
			$records = array();
			$controllersName = $moduleName . DS . 'controllers';
			if ($handle = opendir($controllersName)) {
				while (false !== ($file = readdir($handle))) {
					if ($file != '.' && $file != '..' && $file{0} != '.') {
						if (is_dir($file)) {
							continue;
						}

						// strips .php
						$controllerName = substr($file, 0, -4);
						require_once $controllersName . DS . "{$controllerName}.php";

						if (!preg_match('/(.*)Controller/', $controllerName, $matches)) {
							continue;
						}

						$record['controller'] = strtolower($matches[1]);
						if ($params['name'] != 'default') {
							$controllerName = ucwords($params['name']) . "_{$controllerName}";
						}

						$privileges = array();
						$methods = get_class_methods($controllerName);
						foreach ($methods as $method) {
							// strips Action
							if (preg_match('/(.*)Action/', $method, $matches)) {
								$privileges[] = strtolower($matches[1]);
							}
						}
						$record['privileges'] = $privileges;

						$records[] = $record;
					}
				}
				closedir($handle);
			}

			// create module entry
			$moduleRow = $this->_tableInstance->createRow();
			$moduleRow->name = $params['name'];
			$moduleRow->active = 1;
			$moduleRow->version = $xmlConfig->version;
			$moduleRow->last_update = date('m/d/Y');
			$moduleRow->save();

			$resourceTable = new Philbsd_Model_Resources();
			$privilegeTable = new Philbsd_Model_Privileges();
			foreach ($records as $record) {
				// check if controller/resource name already exists in the resource table, otherwise create a new one
				$resourceRowSet = $resourceTable->fetchAll("name = '{$record['controller']}'");
				if (!$resourceRow = $resourceRowSet->current()) {
					$resourceRow = $resourceTable->createRow();
					$resourceRow->name = $record['controller'];
					$resourceRow->save();
				}

				// create an entry to the module_resources table for references
				$moduleResourceRow = $this->_moduleResourceTable->createRow();
				$moduleResourceRow->module_id = $moduleRow->id;
				$moduleResourceRow->resource_id = $resourceRow->id;
				$moduleResourceRow->save();

				if (!isset($record['privileges'])) {
					continue;
				}

				// create privileges if privilege name does not exists in the privileges table, and create an entry to the module_resource_privileges table for references
				foreach ($record['privileges'] as $priv) {
					$privilegeRowSet = $privilegeTable->fetchAll("name = '{$priv}'");
					if (!$privilegeRow = $privilegeRowSet->current()) {
						$privilegeRow = $privilegeTable->createRow();
						$privilegeRow->name = $priv;
						$privilegeRow->save();
					}
					$moduleResourcePrivilegeRow = $this->_moduleResourcePrivilegeTable->createRow();
					$moduleResourcePrivilegeRow->module_resource_id = $moduleResourceRow->id;
					$moduleResourcePrivilegeRow->privilege_id = $privilegeRow->id;
					$moduleResourcePrivilegeRow->save();
				}
			}

			$this->_session->message = "Module named {$params['name']} successfully installed.";
			$this->_redirect('admin/module');
			//echo "<pre>";
			//print_r($records);
		}

		$this->render();
	}

	public function uninstallAction()
    {
		if (isset($_POST['btnCancel'])) {
			$this->_redirect('admin/module');
		}

		$params = $this->getRequest()->getUserParams();
		// check if id exists in request
		if (!isset($params['id'])) {
			$this->_redirect('admin/module');
		}

		// check if id exists in database, if exists it will redirect back to the module list
		$moduleRowSet = $this->_tableInstance->find($params['id']);
		if (!$moduleRow = $moduleRowSet->current()) {
			$this->_redirect('admin/module');
		}

		// check if module id is still in active mode. before it can be uninstalled it must be deactivated first.
		if ($moduleRow->active) {
			$this->_session->message = "Module named {$params['name']} still active, please deactivate it first.";
			$this->_redirect('admin/module');
		}

		$this->view->record = $moduleRow->toArray();
		if (isset($_POST['btnSubmit'])) {
			$resourceTable = new Philbsd_Model_Resources();
			$privilegeTable = new Philbsd_Model_Privileges();
			$moduleResourceRowSet = $this->_moduleResourceTable->fetchAll("module_id = {$moduleRow->id}");
			while ($moduleResourceRow = $moduleResourceRowSet->current()) {
				$tmpModuleResourceRowSet =
					$this->_moduleResourceTable->fetchAll("resource_id = {$moduleResourceRow->resource_id} AND module_id != {$moduleRow->id}");
				if (!$tmpModuleResourceRow = $tmpModuleResourceRowSet->current()) {
					$resourceRowSet = $resourceTable->find($moduleResourceRow->resource_id);
					if ($resourceRow = $resourceRowSet->current()) {
						$resourceRow->delete();
					}
				}

				$moduleResourcePrivilegeRowSet =
					$this->_moduleResourcePrivilegeTable->fetchAll("module_resource_id = {$moduleResourceRow->id}");

				while ($moduleResourcePrivilegeRow = $moduleResourcePrivilegeRowSet->current()) {
					$whereClause = "privilege_id = {$moduleResourcePrivilegeRow->privilege_id} AND module_resource_id != {$moduleResourceRow->id}";
					$tmpModuleResourcePrivilegeRowSet =
						$this->_moduleResourcePrivilegeTable->fetchAll($whereClause);

					if (!$tmpModuleResourcePrivilegeRow = $tmpModuleResourcePrivilegeRowSet->current()) {
						$privilegeRowSet = $privilegeTable->find($moduleResourcePrivilegeRow->privilege_id);
						if ($privilegeRow = $privilegeRowSet->current()) {
							$privilegeRow->delete();
						}
					}

					$moduleResourcePrivilegeRow->delete();
					$moduleResourcePrivilegeRowSet->next();
				}

				$moduleResourceRow->delete();
				$moduleResourceRowSet->next();
			}

			// delete module now
			$moduleRow->delete();
			$this->_session->message = "Module named {$params['name']} successfully uninstalled.";
			$this->_redirect('admin/module');
		}

        $this->render();
    }
}
